Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AP_Scripting: adjust string metatable setup to fix sandbox integrity #27666

Merged
merged 1 commit into from
Jul 30, 2024

Conversation

tpwrules
Copy link
Contributor

@tpwrules tpwrules commented Jul 26, 2024

In Lua, strings are the only type that come with a default metatable. The metatable must be shared by all string objects, and it is set to be the string library table each time that library is opened. In Ardupilot's scripting engine, the last script to load then has access to the string metatable as the library is opened fresh for each script, as its string library will have been set to the metatable.

Therefore, if two scripts are loaded, A first and B second, and script B executes e.g. string.byte = "haha", then string.byte() and s:byte() for script B are broken. Because the metatable is shared, this also breaks s:byte() for script A, which violates the integrity of the sandbox.

Fix the issue by disabling the metatable setup functionality when the string libary is opened, then manually opening an additional copy of the library (which won't be given to any script) and setting it as the string metatable during intialization.

This will break any script that modifies the string metatable for constructive purposes, but such a script could have been broken if it weren't the only script running anyway.

Tested on SITL and Cube Orange with my REPL. Saves 24 bytes of flash on Cube Orange, but costs 770 bytes of Lua state RAM, which I do not love.

In Lua, strings are the only type that come with a default metatable.
The metatable must be shared by all string objects, and it is set to be
the `string` library table each time that library is opened. In
Ardupilot's scripting engine, the last script to load then has access to
the string metatable as the library is opened fresh for each script, as
its `string` library will have been set to the metatable.

Therefore, if two scripts are loaded, A first and B second, and script B
executes e.g. `string.byte = "haha"`, then `string.byte()` and
`s:byte()` for script B are broken. Because the metatable is shared,
this also breaks `s:byte()` for script A, which violates the integrity
of the sandbox.

Fix the issue by disabling the metatable setup functionality when the
string libary is opened, then manually opening an additional copy of the
library (which won't be given to any script) and setting it as the
string metatable during intialization.

This will break any script that modifies the string metatable for
constructive purposes, but such a script could have been broken if it
weren't the only script running anyway.
Copy link
Member

@bugobliterator bugobliterator left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great Find!

Copy link
Member

@IamPete1 IamPete1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again abit beyond my lua level. We do have tests for the string functionality, so it must still work.

@tridge tridge merged commit dc4d1ba into ArduPilot:master Jul 30, 2024
93 checks passed
@tpwrules tpwrules deleted the pr/scripting-string-sandbox branch July 30, 2024 00:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants